package com.onec.service.channel.service.channel.jft;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.onec.service.api.dto.request.channel.ChannelTradeReq;
import com.onec.service.api.dto.response.channel.ChannelTradeResp;
import com.onec.service.api.enums.ServiceApiEnum;
import com.onec.service.api.enums.StatusEnum;
import com.onec.service.api.enums.error.ChannelErrorEnum;
import com.onec.service.channel.entity.ChannelMerchant;
import com.onec.service.channel.entity.ChannelOrderDetail;
import com.onec.service.channel.service.channel.base.BaseChannelOrderDefaultService;
import com.onec.service.channel.service.channel.jft.util.JftRequestUtils;
import com.onec.service.channel.service.channel.jft.util.JftReturnModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.RoundingMode;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;


/**
 * 对接佳付通支付上游
 *
 * @author ONEC
 */
@Service("order_jft")
public class ChannelOrderJftServiceImpl extends BaseChannelOrderDefaultService {

    private static final Logger logger = LoggerFactory.getLogger(ChannelOrderJftServiceImpl.class);

    @Override
    public RoundingMode getRoundingMode() {
        return RoundingMode.HALF_UP;
    }

    @Override
    public ChannelTradeResp requestWeiXin(ChannelOrderDetail channelOrderDetail) {

        return null;
    }

    @Override
    public ChannelTradeResp requestAliPay(ChannelTradeReq channelTradeReq) {
        return null;
    }

    @Override
    public ChannelTradeResp requestUnionPay(ChannelTradeReq channelTradeReq) {
        return null;
    }

    @Override
    public ChannelTradeResp requestOpen(ChannelTradeReq channelTradeReq) {
        return null;
    }

    @Override
    public ChannelTradeResp requestApiSms(ChannelTradeReq channelTradeReq) {
        return null;
    }

    @Override
    public ChannelTradeResp requestApi(ChannelTradeReq channelTradeReq) {
        return null;
    }

    @Override
    public ChannelTradeResp signUpCard(ChannelTradeReq channelTradeReq) {
        return null;
    }


    @Override
    public ChannelTradeResp unSignUpCard(ChannelTradeReq channelTradeReq) {
        return null;
    }

    @Override
    public ChannelTradeResp repayment(ChannelTradeReq channelTradeReq) {
        return null;
    }


    @Override
    public ChannelTradeResp requestHtml(ChannelOrderDetail orderDetail) {
        ChannelTradeResp channelTradeResp = orderApi(orderDetail);
        channelTradeResp.setReturnType(ServiceApiEnum.trade_html_pay.name());
        return channelTradeResp;
    }

    /**
     * 佳付通订单支付！
     *
     * @param orderDetail
     * @return ChannelTradeResp
     */
    ChannelTradeResp orderApi(ChannelOrderDetail orderDetail) {
        // 处理佳付通2001 业务：
        Map<String, Object> requestParam = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
        requestParam.put("verCode", "1001");
        requestParam.put("orderCode", orderDetail.getTradeNum());
        requestParam.put("orderTime", DateUtil.date());
        requestParam.put("orderAmount", orderDetail.getAmount());
        requestParam.put("settleType", "0");
        requestParam.put("busCode", orderDetail.getChannelBusinessNo());

        requestParam.put("realName", orderDetail.getName());
        requestParam.put("idCard", orderDetail.getIdCard());

        ChannelMerchant channelMerchant = channelMerchantService.getAvailableChannelIdProductMerchantNo(orderDetail.getId(),
                orderDetail.getMerchantNo(), orderDetail.getProduct());

        requestParam.put("chMerCode", channelMerchant.getChannelMerchantNo());
        requestParam.put("accNo", orderDetail.getCardNo());
        requestParam.put("mobile", orderDetail.getPhone());
        requestParam.put("productName", orderDetail.getProduct());
        requestParam.put("productInfo", orderDetail.getSerialNum());
        requestParam.put("frontUrl", this.getOrderFrontUrl(orderDetail.getChannelNo()));

        requestParam.put("callBackUrl", this.getOrderCallBackUrl(orderDetail.getChannelNo()));
        requestParam.put("deviceIP", "1.0.0.2");
        requestParam.put("deviceType", "1");
        requestParam.put("deviceSN", "22222222dddddddddd33");
        requestParam.put("deviceLocation", "+37.12/-21.33.");


        //ChannelKey channelKey = channelKeyService.findByChannelId(channelInfo.getId());
        String sign = JftRequestUtils.getMd5Str(requestParam, jftProperties.getSignKey()).toUpperCase();
        String encryptData = JftRequestUtils.encryptData(requestParam, jftProperties.getEncryptKey());
        Map<String, Object> param = JftRequestUtils.commonMap(jftProperties.getOrgCode(), encryptData, sign);

        String requestUrl = jftProperties.getUrl() + jftProperties.getPayOrder();
        logger.info("佳付通【orderApi】请求：URL:{},请求明文：{}", requestUrl, requestParam);
        JftReturnModel jftReturnModel = JftRequestUtils.requestJft(param, requestUrl, jftProperties.getEncryptKey());

        StatusEnum statusEnum = StatusEnum.DOING;
        if (jftReturnModel.isFailed()) {
            statusEnum = StatusEnum.FAILED;
        }
        ChannelTradeResp channelTradeResp = new ChannelTradeResp();
        channelTradeResp.setMessage(jftReturnModel.getResMsg());
        channelTradeResp.setStatus(statusEnum.name());
        channelTradeResp.setUrl(jftReturnModel.getUrl());
        return respTradeChannelState(channelTradeResp, orderDetail);
    }

    @Override
    public ChannelTradeResp notifyOpenCardApi(HttpServletRequest request) {
        return null;
    }

    /**
     * 处理上游异步通知订单，
     *
     * @param request
     * @return
     */
    @Override
    public ChannelTradeResp notifyOnlineOrderApi(HttpServletRequest request) {

        String notifyStr = getPostString(request);
        logger.info("佳付通【notifyOnlineOrderApi】异步通知：{}，", notifyStr);

        JSONObject notifyJson = receiveJson(notifyStr);
        // 加密数据：
        String encryptData = notifyJson.getString("encryptData");
        encryptData = URLDecoder.decode(encryptData, StandardCharsets.UTF_8);
        JftReturnModel jftReturnModel = null;
        try {
            jftReturnModel = JftRequestUtils.decryptData(encryptData, jftProperties.getEncryptKey());
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Object> requestMap = JSONObject.parseObject(JSONObject.toJSONString(jftReturnModel));
        String signData = notifyJson.getString("signData");
        String sign = JftRequestUtils.getMd5Str(requestMap, jftProperties.getSignKey());
        logger.info("佳付通异步通知验签：signData：{}，sign:{}", signData, sign);
        if (!signData.equals(sign)) {
            return ChannelTradeResp.respTradeStatus(ChannelErrorEnum.SIGN_CHECK_ERROR);
        }

        ChannelOrderDetail channelOrderDetail = channelOrderDetailService
                .findByTradeNum(jftReturnModel.getOrderCode());
        if (Optional.ofNullable(channelOrderDetail).isEmpty()) {
            return ChannelTradeResp.respTradeStatus(ChannelErrorEnum.TRADE_NUM_NOT_EXIST_ERROR);
        }
        ChannelTradeResp channelTradeResp = new ChannelTradeResp();
        StatusEnum statusEnum = StatusEnum.DOING;
        if (jftReturnModel.isTranSuccess()) {
            statusEnum = StatusEnum.SUCCESS;
        }
        channelTradeResp.setTradeNum(jftReturnModel.getOrderCode());
        channelTradeResp.setCompleteTime(jftReturnModel.getTranTime());
        channelTradeResp.setMessage(jftReturnModel.getResMsg());
        channelTradeResp.setStatus(statusEnum.name());
        channelTradeResp.setNotifyMessage("SUCCESS");
        return respTradeChannelState(channelTradeResp, channelOrderDetail);
    }

    @Override
    public ChannelTradeResp notifySettleApi(HttpServletRequest request) {
        return null;
    }

    @Override
    public ChannelTradeResp querySignUpCard(ChannelTradeReq channelTradeReq) {
        return null;
    }

    @Override
    public ChannelTradeResp queryOnlineOrderApi(ChannelOrderDetail orderDetail) {
        // 处理佳付通2001 业务：
        Map<String, Object> requestParam = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
        requestParam.put("verCode", "1001");
        requestParam.put("orderCode", orderDetail.getTradeNum());
        requestParam.put("chMerCode", orderDetail.getChannelMerchantNo());

        String sign = JftRequestUtils.getMd5Str(requestParam, jftProperties.getSignKey()).toUpperCase();
        String encryptData = JftRequestUtils.encryptData(requestParam, jftProperties.getEncryptKey());
        Map<String, Object> param = JftRequestUtils.commonMap(jftProperties.getOrgCode(), encryptData, sign);
        String requestUrl = jftProperties.getUrl() + jftProperties.getTradeQuery();
        logger.info("佳付通【queryOnlineOrderApi】请求：URL:{},请求明文：{}", requestUrl, requestParam);
        JftReturnModel jftReturnModel = JftRequestUtils.requestJft(param, requestUrl, jftProperties.getEncryptKey());

        ChannelTradeResp channelTradeResp = new ChannelTradeResp();
        StatusEnum statusEnum = StatusEnum.DOING;
        if (jftReturnModel.isTranSuccess()) {
            statusEnum = StatusEnum.SUCCESS;
        } else if (jftReturnModel.isError()) {
            statusEnum = StatusEnum.DOING;
        } else if (jftReturnModel.isFailed()) {
            statusEnum = StatusEnum.FAILED;
        }
        channelTradeResp.setMessage(jftReturnModel.getResMsg());
        channelTradeResp.setStatus(statusEnum.name());
        return respTradeChannelState(channelTradeResp, orderDetail);
    }

    @Override
    public ChannelTradeResp queryRepayment(ChannelTradeReq channelTradeReq) {
        return null;
    }

    @Override
    public void afterPropertiesSet() {

    }
}
